import { toolchain } from "../toolchain.js";

export class SVNHelper {
    public static async pullPublish(): Promise<void> {
        const urlMap = toolchain.params.svn.urlMap;
        console.log('========== xlsx ==========');

        if (await SVNHelper.exists(urlMap.xls.publish)) {
            console.log('----');
            await SVNHelper.back_publish_bytag(urlMap.xls.publish, urlMap.xls.publishTag);
    
            console.log('----');
            await SVNHelper.delete_publish(urlMap.xls.publish);
        }

        console.log('----');
        await SVNHelper.tag_trunk(urlMap.xls.develop, urlMap.xls.developTag);
    
        console.log('----');
        await SVNHelper.pullpublish_from_backtrunktag(urlMap.xls.developTag, urlMap.xls.publish);

        console.log('========== code ==========')

        if (await SVNHelper.exists(urlMap.code.publish)) {
            console.log('----');
            await SVNHelper.back_publish_bytag(urlMap.code.publish, urlMap.code.publishTag);
    
            console.log('----');
            await SVNHelper.delete_publish(urlMap.code.publish);
        }
        
        console.log('----');
        await SVNHelper.tag_trunk(urlMap.code.develop, urlMap.code.developTag);
    
        console.log('----');
        await SVNHelper.pullpublish_from_backtrunktag(urlMap.code.developTag, urlMap.code.publish);
        
        console.log('----');
        await SVNHelper.copy_singlefile_from_backpublishtag('versionCode.txt');
        await SVNHelper.copy_singlefile_from_backpublishtag('apks.txt');
    }

    public static async getVersion(pathOrUrl: string): Promise<string> {
        let log = await toolchain.svnClient.cmd('log', [pathOrUrl, '-l', '1']);
        let match = log.match(/r(\d+)/);
        let codever = (match && match[1]);
        return codever!;
    }

    private static async exists(url: string): Promise<boolean> {
        try {
            await toolchain.svnClient.info(url);
        } catch(e) {
            if (e instanceof Error && (e.message.includes('E200009') || e.message.includes('E160013'))) {
                // E200009: folder not exists
                // E160013: file not exists
                return false;
            }
        }
        return true;
    }

    // 备份publish
    private static async back_publish_bytag(puburl: string, pubtagurl: string): Promise<void> {
        console.log('copy publish to tag: ' + pubtagurl);
        await toolchain.svnClient.copy(puburl, pubtagurl, { message: 'auto by builder' });
    }

    // 删除publish
    private static async delete_publish(puburl: string): Promise<void> {
        console.log('delete publish...');
        try {
            await toolchain.svnClient.delete(puburl, { message: 'auto by builder' });
        } catch(e) {
            if (e instanceof Error) {
                const mch = e.message.match(/(?<=does not own lock on path '\/branches\/publish)[^'+]+(?=')/);
                if (mch != null) {
                    const lockedFile = mch[0];
                    console.log('auto unlock:', lockedFile);
                    await toolchain.svnClient.unlock(puburl + lockedFile, { force: true });
                    console.log('delete again');
                    await toolchain.svnClient.delete(puburl, {message: 'auto by builder' });
                } else {
                    console.error(e);
                    process.exit(1);
                }
            }            
        }
    }
        
    // 给develop项目打tag
    private static async tag_trunk(devurl: string, devtagurl: string): Promise<void> {
        console.log('back code by tag:', devtagurl)
        await toolchain.svnClient.copy(devurl,  devtagurl, { message: 'auto by builder' });
    }
        
    // 拉publish分支
    private static async pullpublish_from_backtrunktag(devtagurl: string, puburl: string): Promise<void> {
        console.log('pull code publish from tag:', devtagurl);
        await toolchain.svnClient.copy(devtagurl, puburl, { message: 'auto by builder' });
    }

    private static async copy_singlefile_from_backpublishtag(filename: string): Promise<void> {
        const from = toolchain.params.svn.urlMap.code.publishTag + '/project/build/' + filename;
        if (await SVNHelper.exists(from)) {
            const to = toolchain.params.svn.urlMap.code.publish + '/project/build/';
            console.log('copy from ' + from + ' to ' + to);
            await toolchain.svnClient.copy(from, to + filename + '.bak', { message: 'auto by builder' });
            await toolchain.svnClient.delete([to + filename], { message: 'auto by builder' });
            await toolchain.svnClient.copy(to + filename + '.bak', to + filename, { message: 'auto by builder' });
        } else {
            console.log('skip copy cause src not exists:', from);
        }
    }
}
